package com.fakeDYChat.common.user.service.impl;

import com.fakeDYChat.common.user.dao.UserDao;
import com.fakeDYChat.common.user.domain.entity.User;
import com.fakeDYChat.common.user.service.IUserService;
import com.fakeDYChat.common.user.service.WxMsgService;
import com.fakeDYChat.common.user.service.adapter.TextBuilder;
import com.fakeDYChat.common.user.service.adapter.UserAdapter;
import com.fakeDYChat.common.websocket.service.WebSocketService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 用于微信消息处理
 *
 * @author Tang
 * @date 2023/12/11 11:06
 **/
@Slf4j
@Service
public class WxMsgServiceImpl implements WxMsgService {
    //用户信息操作接口
    private final UserDao userDao;
    //用户功能接口
    private final IUserService IUserService;
    //WebSocket服务
    @Lazy
    @Resource
    private WebSocketService webSocketService;
    //回调地址
    @Value("${mallchat.wx.callback}")
    private String callback;
    //授权链接
    public static final String URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
    //openId-code对应关系
    private static final ConcurrentMap<String, Integer> OPENID_CODE_MAP = new ConcurrentHashMap<>();

    public WxMsgServiceImpl(UserDao userDao, IUserService IUserService) {
        this.userDao = userDao;
        this.IUserService = IUserService;
    }

    /**
     * 用户扫码
     *
     * @param wxService
     * @param wxMpXmlMessage
     * @return me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage
     * @author Tang
     * @date 2023/12/10 18:33
     **/
    @Override
    public WxMpXmlOutMessage scan(WxMpService wxService, WxMpXmlMessage wxMpXmlMessage) {
        //获取openId
        String openId = wxMpXmlMessage.getFromUser();
        //获取事件码
        Integer eventKey = Integer.parseInt(getEventKey(wxMpXmlMessage));
        //关联openId和事件码
        linkOpenIdAndCode(openId, eventKey);
        //推送扫码成功消息（根据code对应的链接）
        webSocketService.handleScanSuccess(eventKey);
        //查询用户
        User user = userDao.getUserOneByOpenId(openId);
        //已注册的用户
        boolean register = Objects.nonNull(user);
        boolean authorized = register && StringUtils.isNotEmpty(user.getAvatar());
        if (register && authorized) {
            //todo 登录逻辑
            webSocketService.scanLoginSuccess(eventKey, user.getId());
            return TextBuilder.build("登录成功！", wxMpXmlMessage, wxService);
        }
        //未注册的用户
        if (!register) {
            User registerUser = UserAdapter.buildRegisterUser(openId);
            IUserService.register(registerUser);
        }
        return authorize(wxService, wxMpXmlMessage);
    }

    /**
     * 补全用户信息
     *
     * @param userInfo
     * @return void
     * @author Tang
     * @date 2023/12/11 11:38
     **/
    @Override
    public void fillUserInfo(WxOAuth2UserInfo userInfo) {
        User user = userDao.getUserOneByOpenId(userInfo.getOpenid());
        if (StringUtils.isEmpty(user.getAvatar())) {
            //更新用户信息
            userDao.updateUserInfo(UserAdapter.buildFillInfoUser(userInfo));
        }
        //登录
        webSocketService.scanLoginSuccess(OPENID_CODE_MAP.remove(userInfo.getOpenid()), user.getId());
    }

    private void linkOpenIdAndCode(String openId, Integer code) {
        //关联OpenId和随机码Code
        OPENID_CODE_MAP.put(openId, code);
    }

    /**
     * 用户授权
     *
     * @param wxMpXmlMessage
     * @return me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage
     * @author Tang
     * @date 2023/12/10 17:54
     **/
    private WxMpXmlOutMessage authorize(WxMpService wxMpService, WxMpXmlMessage wxMpXmlMessage) {
        log.info("{}", wxMpXmlMessage);
        //todo 扫码事件处理
        //获取appId
        String appId = wxMpService.getWxMpConfigStorage().getAppId();
        //重定向地址
        String redirect = callback + "/wx/portal/public/callBack";
        //请求链接
        String authorURL;
        try {
            authorURL = String.format(URL, appId, URLEncoder.encode(redirect, "utf-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        //推送授权链接
        return TextBuilder.build("请点击链接授权：" + "<a href=\"" + authorURL + "\">" + "登录" + "</a>", wxMpXmlMessage, wxMpService);
    }

    /**
     * 获取事件码
     *
     * @param wxMpXmlMessage
     * @return java.lang.String
     * @author Tang
     * @date 2023/12/10 17:45
     **/
    private String getEventKey(WxMpXmlMessage wxMpXmlMessage) {
        //扫码关注的渠道事件有前缀，需要去除
        return wxMpXmlMessage.getEventKey().replace("qrscene_", "");
    }
}
